#include <iostream>
#include <windows.h>
using namespace std;
int map[30][30];//0 = ��,1 = ̹��,2 = �ڵ�,3 = ����
int cover[30][30];//����

struct coords {

	int X;
	int Y;

};//����

void gotoxy(int x, int y)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;                                     
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

struct shell {
	coords S_coords[30];
	int S_length;
	int S_direction[30];
};

struct tank {

	coords head;//ͷ����ʱX���귶Χ2-29,Y����1-28
				//ͷ����ʱX���귶Χ0-27,Y����1-28
				//ͷ����ʱX���귶Χ1-28,Y����0-27
				//ͷ����ʱX���귶Χ1-28,Y����2-29

	coords border[7];//		h	ͷ
					 //	   123	border1-3
					 //	   456	border4-6

	shell S_shell;//�ڵ�����

	int direction;//����
				  //1��
				  //2��
				  //3��
				  //4��
	int direction_last;
	int life;//����;
	int made_kill;
};//̹������

static void draw(int life1,int life2)//����
{
	gotoxy(0, 0);
	cout << "=== = = = = = T A N K = = = = = = = = W A R = = = = = = = = ==" << endl;
	for (int i = 0; i < 30; i++)
	{
		cout << "=";
		for (int s = 0; s < 30; s++)
		{
			if (map[i][s] == 1)
			{
				cout << "O ";
			}
			else
			{
				if (map[i][s] == 2)
				{
					cout << "@ ";
				}
				else {
					if (map[i][s] == 3)
					{
						cout << "& ";
					}
					else {
						cout << "  ";
					}
				}
			}
		}cout << "=";
		if (i == 2)
		{
			cout << "	���һ:W, A, S, D�ƶ�,V���";
		}if (i == 4)
		{
			cout << "	��Ҷ�:������ƶ�,L���";
		}if (i == 6)
		{
			cout << "	���һ����ֵ[ ";
			for (int v = 0; v < life1; v++)
			{
				cout << "@ ";
			}
			for (int v = life1; v < 10; v++)
			{
				cout << "  ";
			}
			cout << "]";
		}if (i == 8)
		{
			cout << "	��Ҷ�����ֵ[ ";
			for (int v = 0; v < life2; v++)
			{
				cout << "@ ";
			}
			for (int v = life2; v < 10; v++)
			{
				cout << "  ";
			}
			cout << "]";
		}cout << endl;
	}cout << "=== = = = = = = = = = = = = = = = = = = = = = = = = = = = = ==" << endl;
}
static void initialize_cover()
{
//=== = = = = = T A N K = = = = = = = = W A R = = = = = = = = ==
//=                                                            =
//=                                                            =
//=                                                            =
//=                                                            =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &                               & & &             =
//=      & & &                               & & &             =
//=      & & &                               & & &             =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &                               & & &             =
//=      & & &                               & & &             =
//=      & & &                               & & &             =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &                               & & &             =
//=      & & &                               & & &             =
//=      & & &                               & & &             =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=      & & &       & & &       & & &       & & &       & & & =
//=                                                            =
//=                                                            =
//=                            O                               =
//=                          O O O                             =
//=                          O O O                             =
//=== = = = = = = = = = = = = = = = = = = = = = = = = = = = = ==	������ʽ
	for (int i = 0; i < 30; i++)
	{
		for (int s = 0; s < 30; s++)
		{
			cover[i][s] = 0;
		}
	}
	for (int i = 4; i < 25; i++)
	{
		for (int a = 3; a < 29; a += 18)
		{
			for (int s = 0; s < 3; s++)
			{
				cover[i][a + s] = 1;
			}
		}
	}
	for (int i = 4; i < 25; i += 6)
	{
		for (int a = 9; a < 12; a++)
		{
			cover[i][a] = 1; cover[i+1][a] = 1; cover[i + 2][a] = 1;
		}for (int a = 15; a < 18; a++)
		{
			cover[i][a] = 1; cover[i + 1][a] = 1; cover[i + 2][a] = 1;
		}for (int a = 27; a < 30; a++)
		{
			cover[i][a] = 1; cover[i + 1][a] = 1; cover[i + 2][a] = 1;
		}
	}


}
static void initialize()//���Ƴ�ʼ��
{
	for (int i = 0; i < 30; i++)
	{
		for (int s = 0; s < 30; s++)
		{
			if (cover[i][s] == 1)
			{
				map[i][s] = 3;
			}
			else {
				map[i][s] = 0;
			}
		}
	}//��ʼ������
	
}
static void initialize_tank(tank tk)//��ʼ��̹��
{
	map[tk.head.X][tk.head.Y] = 1;
	for (int i = 1; i < 7; i++)
	{
		map[tk.border[i].X][tk.border[i].Y] = 1;
	}
	if (tk.S_shell.S_length > 0)
	{
		for (int i = 1; i <= tk.S_shell.S_length; i++)
		{
			map[tk.S_shell.S_coords[i].X][tk.S_shell.S_coords[i].Y] = 2;
		}
	}
}

bool collision_detection(tank tk, int x, int y)//̹��������ײ
{
	if (cover[tk.head.X + x][tk.head.Y + y] == 1)
	{
		return false;
	}
	for (int i = 1; i < 7; i++)
	{
		if (cover[tk.border[i].X + x][tk.border[i].Y + y] == 1)
		{
			return false;
		}
		else {
			return true;
		}
	}
}

static tank tank_h_and_border(tank tk)
{
	//tk.border[1,2,3].X = tk.head.X + 1;	tk.border[1,2,3].X = tk.head.X - 1;		tk.border[1,2,3].Y = tk.head.Y + 1;		tk.border[1,2,3].Y = tk.head.Y - 1;
	//tk.border[4,5,6].X = tk.head.X + 2;	tk.border[4,5,6].X = tk.head.X - 2;		tk.border[4,5,6].Y = tk.head.Y + 2;		tk.border[4,5,6].Y = tk.head.Y - 2;
	//������Ϊ��ʱ							������Ϊ��ʱ							������Ϊ��ʱ							������Ϊ��ʱ
	//tk.border[1,4].Y = tk.head.Y - 1;		tk.border[1,4].Y = tk.head.Y + 1;		tk.border[1,4].X = tk.head.X + 1;		tk.border[1,4].X = tk.head.X - 1;
	//tk.border[2,5].Y = tk.head.Y;			tk.border[2,5].Y = tk.head.Y;			tk.border[2,5].X = tk.head.X;			tk.border[2,5].X = tk.head.X;
	//tk.border[3,6].Y = tk.head.Y + 1;		tk.border[3,6].Y = tk.head.Y - 1;		tk.border[3,6].X = tk.head.X - 1		tk.border[3,6].X = tk.head.X + 1;

	if (tk.direction == 1)
	{
		tk.border[1].X = tk.head.X + 1; tk.border[2].X = tk.head.X + 1; tk.border[3].X = tk.head.X + 1;
		tk.border[4].X = tk.head.X + 2; tk.border[5].X = tk.head.X + 2; tk.border[6].X = tk.head.X + 2;//X��

		tk.border[1].Y = tk.head.Y - 1; tk.border[4].Y = tk.head.Y - 1;
		tk.border[2].Y = tk.head.Y; tk.border[5].Y = tk.head.Y;
		tk.border[3].Y = tk.head.Y + 1; tk.border[6].Y = tk.head.Y + 1;//Y��
	}
	if (tk.direction == 2)
	{
		tk.border[1].X = tk.head.X - 1; tk.border[2].X = tk.head.X - 1; tk.border[3].X = tk.head.X - 1;
		tk.border[4].X = tk.head.X - 2; tk.border[5].X = tk.head.X - 2; tk.border[6].X = tk.head.X - 2;//X��

		tk.border[1].Y = tk.head.Y + 1; tk.border[4].Y = tk.head.Y + 1;
		tk.border[2].Y = tk.head.Y; tk.border[5].Y = tk.head.Y;
		tk.border[3].Y = tk.head.Y - 1; tk.border[6].Y = tk.head.Y - 1;//Y��
	}
	if (tk.direction == 3)
	{
		tk.border[1].Y = tk.head.Y + 1; tk.border[2].Y = tk.head.Y + 1; tk.border[3].Y = tk.head.Y + 1;
		tk.border[4].Y = tk.head.Y + 2; tk.border[5].Y = tk.head.Y + 2; tk.border[6].Y = tk.head.Y + 2;//Y��

		tk.border[1].X = tk.head.X + 1; tk.border[4].X = tk.head.X + 1;
		tk.border[2].X = tk.head.X; tk.border[5].X = tk.head.X;
		tk.border[3].X = tk.head.X - 1; tk.border[6].X = tk.head.X - 1;//X��
	}
	if (tk.direction == 4)
	{
		tk.border[1].Y = tk.head.Y - 1; tk.border[2].Y = tk.head.Y - 1; tk.border[3].Y = tk.head.Y - 1;
		tk.border[4].Y = tk.head.Y - 2; tk.border[5].Y = tk.head.Y - 2; tk.border[6].Y = tk.head.Y - 2;//Y��

		tk.border[1].X = tk.head.X - 1; tk.border[4].X = tk.head.X - 1;
		tk.border[2].X = tk.head.X; tk.border[5].X = tk.head.X;
		tk.border[3].X = tk.head.X + 1; tk.border[6].X = tk.head.X + 1;//X��
	}
	return tk;
}

static tank shell_collision(tank tk,tank tk2)
{
	if (tk.S_shell.S_length > 0)
	{
		for (int i = 1; i <= tk.S_shell.S_length; i++)
		{
			switch (tk.S_shell.S_direction[i])
			{
			case 1:--tk.S_shell.S_coords[i].X;
				break;
			case 2:++tk.S_shell.S_coords[i].X;
				break;
			case 3:--tk.S_shell.S_coords[i].Y;
				break;
			case 4:++tk.S_shell.S_coords[i].Y;
				break;
			}
			if (tk.S_shell.S_coords[i].X < 0 || tk.S_shell.S_coords[i].X > 29 || tk.S_shell.S_coords[i].Y < 0 || tk.S_shell.S_coords[i].Y > 29 || cover[tk.S_shell.S_coords[i].X][tk.S_shell.S_coords[i].Y] == 1)
			{
				cover[tk.S_shell.S_coords[i].X][tk.S_shell.S_coords[i].Y] = 0;
				for (int s = i; s < tk.S_shell.S_length; s++)
				{
					tk.S_shell.S_coords[s].X = tk.S_shell.S_coords[s + 1].X;
					tk.S_shell.S_coords[s].Y = tk.S_shell.S_coords[s + 1].Y;
					tk.S_shell.S_direction[s] = tk.S_shell.S_direction[s + 1];
				}tk.S_shell.S_length--;
			}
			for (int v = 1; v < 7; v++)
			{
				if (tk2.border[v].X == tk.S_shell.S_coords[i].X && tk2.border[v].Y == tk.S_shell.S_coords[i].Y)
				{
					for (int s = i; s < tk.S_shell.S_length; s++)
					{
						tk.S_shell.S_coords[s].X = tk.S_shell.S_coords[s + 1].X;
						tk.S_shell.S_coords[s].Y = tk.S_shell.S_coords[s + 1].Y;
						tk.S_shell.S_direction[s] = tk.S_shell.S_direction[s + 1];
					}tk.S_shell.S_length--; tk.made_kill++;
				}
			}
		}
	}return tk;
	//�ڵ���ײ
}

static tank control(tank tk, char up, char down, char left, char right,char ki)//���ƺ���
{
	if (GetAsyncKeyState(up) & 0x8000) {
		tk.direction_last = tk.direction;
		if (tk.head.X > 0 && collision_detection(tk, -1, 0))
		{
			--tk.head.X;
			tk.direction = 1;
		}
	}if (GetAsyncKeyState(down) & 0x8000) {
		tk.direction_last = tk.direction;
		if (tk.head.X < 29 && collision_detection(tk, 1, 0))
		{
			++tk.head.X;
			tk.direction = 2;
		}
	}if (GetAsyncKeyState(left) & 0x8000) {
		tk.direction_last = tk.direction;
		if (tk.head.Y > 0 && collision_detection(tk, 0, -1))
		{
			--tk.head.Y;
			tk.direction = 3;
		}
	}if (GetAsyncKeyState(right) & 0x8000) {
		tk.direction_last = tk.direction;
		if (tk.head.Y < 29 && collision_detection(tk, 0, +1))
		{
			++tk.head.Y;
			tk.direction = 4;
		}
	}if (GetAsyncKeyState(ki) & 0x8000) {
		tk.S_shell.S_length++;
		tk.S_shell.S_coords[tk.S_shell.S_length].X = tk.head.X;
		tk.S_shell.S_coords[tk.S_shell.S_length].Y = tk.head.Y;
		tk.S_shell.S_direction[tk.S_shell.S_length] = tk.direction;
	}
	return tk;
}

void game_over(int life1,int life2)
{
	if (life1 > life2)
	{
		for (int i = 0; i < 5; i++)
		{
			system("cls");
			cout << "���һ��ʤ";
		}
	}
	else {
		for (int i = 0; i < 5; i++)
		{
			system("cls");
			cout << "��Ҷ���ʤ";
		}
	}cout << endl;
	system("pause");
	exit(0);
}

int main()
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(handle, &CursorInfo);
	CursorInfo.bVisible = false;
	SetConsoleCursorInfo(handle, &CursorInfo);

	
	initialize_cover();
	tank tk; tank tk2;
	tk.head.X = 27; tk.head.Y = 14;
	tk.direction = 1;
	tk = tank_h_and_border(tk);
	tk.S_shell.S_length = 0;
	tk.life = 10; tk.made_kill = 0;

	tk2.head.X = 2; tk2.head.Y = 14;
	tk2.direction = 2;
	tk2 = tank_h_and_border(tk2);
	tk2.S_shell.S_length = 0;
	tk2.life = 10; tk2.made_kill = 0;


	while (1)
	{
		tk = shell_collision(tk,tk2);//�ڵ���ײ
		tk2 = shell_collision(tk2,tk);//�ڵ���ײ

		tk.life -= tk2.made_kill; tk2.made_kill = 0;
		tk2.life -= tk.made_kill; tk.made_kill = 0;

		if (tk.life < 1 || tk2.life < 1)//��Ϸ����
		{
			game_over(tk.life, tk2.life);
		}

		if (tk.head.X == 0 && tk.direction != 1)
		{
			++tk.head.X;
		}if (tk.head.X == 29 && tk.direction != 2)
		{
			--tk.head.X;
		}if (tk.head.Y == 0 && tk.direction != 3)
		{
			++tk.head.Y;
		}if (tk.head.Y == 29 && tk.direction != 4)
		{
			--tk.head.Y;
		}
		
		if (tk2.head.X == 0 && tk2.direction != 1)
		{
			++tk2.head.X;
		}if (tk2.head.X == 29 && tk2.direction != 2)
		{
			--tk2.head.X;
		}if (tk2.head.Y == 0 && tk2.direction != 3)
		{
			++tk2.head.Y;
		}if (tk2.head.Y == 29 && tk2.direction != 4)
		{
			--tk2.head.Y;
		}

		Sleep(100);
		tk = tank_h_and_border(tk);//̹���������
		tk2 = tank_h_and_border(tk2);//̹���������
		initialize();//��ʼ��
		initialize_tank(tk);//��ʼ��
		initialize_tank(tk2);//��ʼ��
		draw(tk.life,tk2.life);//����
		tk = control(tk, 'W', 'S', 'A', 'D', 'V');
		tk2 = control(tk2, VK_UP, VK_DOWN,VK_LEFT,VK_RIGHT, 'L');
	}

	return 0;
}